package com.seabook.imgdownloader.core;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.Text;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.NodeVisitor;

import com.seabook.imgdownloader.entity.ImageSymbol;
import com.seabook.imgdownloader.srchandler.ImgSrcHandler;

public class ImgSourceExtractor {
	private String prefix;
	private String suffix;
	private String regex;

	private ImgSrcHandler imgSrcHandler;

	private List<String> extractedImgSrcs = new ArrayList<String>();
	private NodeVisitor visitor = new ImageNodeVisitor();
	private Parser parser = new Parser();

	public void extractImgSrcs(String url) {
		try {
			parser.setURL(url);
			parser.visitAllNodesWith(visitor);
			addImgPrefix();
			addImgSuffix();
			filterImgSrcs();
			validateImgSrcs();
		} catch (ParserException e) {
			e.printStackTrace();
		}
	}

	private void addImgPrefix() {
		if (StringUtils.isEmpty(prefix)) {
			return;
		}
		for (int i = 0; i < extractedImgSrcs.size(); i++) {
			String imgSrc = extractedImgSrcs.get(i);
			imgSrc = prefix + imgSrc;
			extractedImgSrcs.set(i, imgSrc);
		}
	}

	private void addImgSuffix() {
		if (StringUtils.isEmpty(suffix)) {
			return;
		}
	}

	private void validateImgSrcs() {
		// Copy extractorImgSrcs set to avoid ConcurrentModification Exception
		List<String> copyImgSrcs = new ArrayList<String>(extractedImgSrcs);
		for (String imgSrc : copyImgSrcs) {
			if (!isValidImgSrc(imgSrc)) {
				extractedImgSrcs.remove(imgSrc);
				System.err
						.println("Invalid ImgSrc, Please do more investigation before downloading the image: "
								+ imgSrc);
			}
		}
	}

	private boolean isValidImgSrc(String src) {
		if (StringUtils.isEmpty(src)) {
			return false;
		}

		if (!src.startsWith("http://")) {
			return false;
		}

		ImageSymbol[] symbols = ImageSymbol.values();

		for (ImageSymbol symbol : symbols) {
			if (src.endsWith(symbol.getImgSymbol())) {
				return true;
			}
		}
		return false;
	}

	private void filterImgSrcs() {
		if (StringUtils.isEmpty(regex)) {
			return;
		}

		// Copy extractorImgSrcs set to avoid ConcurrentModification Exception
		List<String> copyImgSrcs = new ArrayList<String>(extractedImgSrcs);
		for (String str : copyImgSrcs) {
			if (!str.contains(regex)) {
				extractedImgSrcs.remove(str);
			}
		}
	}

	private class ImageNodeVisitor extends NodeVisitor {

		public void visitTag(Tag tag) {
			String imageSrc = imgSrcHandler.handleImageSrc(tag);
			if (StringUtils.isNotEmpty(imageSrc)) {
				extractedImgSrcs.add(imageSrc);
			}
		}

		public void visitStringNode(Text string) {

		}
	}

	public String getPrefix() {
		return prefix;
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public String getSuffix() {
		return suffix;
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

	public String getRegex() {
		return regex;
	}

	public void setRegex(String regex) {
		this.regex = regex;
	}

	public ImgSrcHandler getImgSrcHandler() {
		return imgSrcHandler;
	}

	public void setImgSrcHandler(ImgSrcHandler imgSrcHandler) {
		this.imgSrcHandler = imgSrcHandler;
	}

	public List<String> getExtractorImgSrcs() {
		return extractedImgSrcs;
	}

	public void setExtractorImgSrcs(List<String> extractedImgSrcs) {
		this.extractedImgSrcs = extractedImgSrcs;
	}

}
